package com.digitaldreamers.framework.scene;

import org.andengine.engine.Engine;
import org.andengine.engine.camera.hud.HUD;
import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.entity.scene.Scene;

import com.digitaldreamers.framework.BaseResourceManager;
import com.digitaldreamers.framework.scene.layer.ManagedLayer;
public class SceneManager {
	private static Object lockObj = new Object();
	private static SceneManager instance;
	
	public ManagedScene mCurrentScene;
	public ManagedLayer mCurrentLayer;
	public boolean mIsLayerShown = false;
	protected int mNumFamesPassed;
	protected boolean mLoadingSceneHandlerRegistered;
	protected boolean mCameraHadHud;
	protected ManagedScene mNextScene;
	protected Engine mEngine;
	protected Scene mPlaceholderModalScene;
	protected BaseResourceManager mBaseResourceManager;
	private IUpdateHandler mLoadingSceneHandler;
	
	private SceneManager() {
		this.mNumFamesPassed = -1;
		this.mLoadingSceneHandlerRegistered = false;
		this.mCameraHadHud = false;
		this.mIsLayerShown = false;
		this.mBaseResourceManager = BaseResourceManager.getInstance();
		this.mEngine = this.mBaseResourceManager.mEngine;
		this.mLoadingSceneHandler = new IUpdateHandler() {
			@Override
			public void onUpdate(float secondsElapsed) {
				SceneManager.this.mNumFamesPassed++;
				SceneManager.this.mNextScene.mElapsedLoadingScreneTime += secondsElapsed;
				if(SceneManager.this.mNumFamesPassed == 1) {
					if(SceneManager.this.mCurrentScene!=null) {
						SceneManager.this.mCurrentScene.onHideManagedScene();
						SceneManager.this.mCurrentScene.onUnloadManagedScene();
					}
					SceneManager.this.mNextScene.onLoadManagedScene();
				}
				
				if(SceneManager.this.mNumFamesPassed > 1 &&
						SceneManager.this.mNextScene.mElapsedLoadingScreneTime >= SceneManager.this.mNextScene.mMinLoadingSceneTime &&
						SceneManager.this.mNextScene.mIsLoaded) {
					SceneManager.this.mNextScene.clearChildScene();
					SceneManager.this.mNextScene.onLoadingSceneUnloadAndHidden();
					SceneManager.this.mNextScene.onShowManagedScene();
					SceneManager.this.mCurrentScene = SceneManager.this.mNextScene;
					SceneManager.this.mNextScene.mElapsedLoadingScreneTime = 0f;
					SceneManager.this.mNumFamesPassed = -1;
					SceneManager.this.mEngine.unregisterUpdateHandler(this);
					SceneManager.this.mLoadingSceneHandlerRegistered = false;
				}
			}
			
			@Override public void reset() {
				
			}
		};
	}
	
	public static SceneManager getInstance(){
		if(instance == null) {
			synchronized(lockObj) {
				if(instance == null) {
					instance = new SceneManager();
				}
			}
		}
		return instance;
	}
	
	public void showScene(final ManagedScene managedScene) {
		this.mEngine.getCamera().set(0, 0, this.mBaseResourceManager.mCameraWidth, this.mBaseResourceManager.mCameraHeight);
		if(managedScene.mHasLoadingScene) {
			managedScene.setChildScene(managedScene.onLoadingSceneLoadAndShown(), true, true, true);
			if(this.mLoadingSceneHandlerRegistered) {
				this.mNumFamesPassed = -1;
				this.mNextScene.clearChildScene();
				this.mNextScene.onLoadingSceneUnloadAndHidden();
			} else {
				this.mEngine.registerUpdateHandler(this.mLoadingSceneHandler);
				this.mLoadingSceneHandlerRegistered = true;
			}
			this.mNextScene = managedScene;
			this.mEngine.setScene(managedScene);
			return;
		}
		
		this.mNextScene = managedScene;
		this.mEngine.setScene(this.mNextScene);
		if(this.mCurrentScene != null) {
			this.mCurrentScene.onHideManagedScene();
			this.mCurrentScene.onUnloadManagedScene();
		}
		this.mNextScene.onLoadManagedScene();
		this.mNextScene.onShowManagedScene();
		this.mCurrentScene = this.mNextScene;
	}
	
	public void showLayer(final ManagedLayer layer, final boolean isSuspendSceneDrawing, final boolean isSuspendSceneUpdates, final boolean isSuspendSceneTouchEvents) {
		if(this.mEngine.getCamera().hasHUD()) {
			this.mCameraHadHud = true;
		} else {
			this.mCameraHadHud = false;
			HUD placeholderHud = new HUD();
			this.mEngine.getCamera().setHUD(placeholderHud);
		}
		if(isSuspendSceneDrawing || isSuspendSceneUpdates || isSuspendSceneTouchEvents) {
			this.mEngine.getCamera().getHUD().setChildScene(layer, isSuspendSceneDrawing, isSuspendSceneUpdates, isSuspendSceneTouchEvents);
			this.mEngine.getCamera().getHUD().setOnSceneTouchListenerBindingOnActionDownEnabled(true);
			if(this.mPlaceholderModalScene == null) {
				this.mPlaceholderModalScene = new Scene();
				this.mPlaceholderModalScene.setBackgroundEnabled(false);
			}
			this.mCurrentScene.setChildScene(this.mPlaceholderModalScene, isSuspendSceneDrawing, isSuspendSceneUpdates, isSuspendSceneTouchEvents);
		} else {
			this.mEngine.getCamera().getHUD().setChildScene(layer);
		}
		layer.setCamera(this.mEngine.getCamera());
		layer.onShowManagedLayer();
		this.mIsLayerShown = true;
		this.mCurrentLayer = layer;
	}
	
	public void hideLayer() {
		if(this.mIsLayerShown) {
			this.mEngine.getCamera().getHUD().clearChildScene();
			if(this.mCurrentScene.hasChildScene()) {
				if(this.mCurrentScene.getChildScene() == this.mPlaceholderModalScene) {
					this.mCurrentScene.clearChildScene();
				}
			}
			if(!this.mCameraHadHud) {
				this.mEngine.getCamera().setHUD(null);
			}
			this.mIsLayerShown = false;
			this.mCurrentLayer = null;
		}
	}
}